package com.chaike.hsq.service;

import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.chaike.common.util.Base64UC;
import com.chaike.common.util.StringUC;
import com.chaike.common.util.ValidateUC;
import com.chaike.hsq.bean.response.BaseHsqResponse;
import com.chaike.hsq.consts.HsqConsts;
import com.chaike.hsq.exception.HuiShouQianCheckException;
import com.chaike.hsq.exception.HuiShouQianException;
import com.chaike.hsq.exception.HuiShouQianRuntimeException;
import com.chaike.hsq.service.impl.HsqCommonService;
import com.chaike.hsq.service.impl.HsqMerchantService;
import com.chaike.hsq.service.impl.HsqPayService;
import com.chaike.hsq.storage.HsqConfigStorage;
import com.chaike.hsq.utils.RsaUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;

/**
 * 慧收钱客户端.
 *
 * @author Luo
 * @version 1.0
 * @date 2021-12-31 10:51:00
 */
@Data
@Slf4j
public abstract class BaseHsqService implements HuiShouQianService {

    /**
     * 重试间隔.
     */
    private static final int RETRY_SLEEP_MILLIS = 1000;

    /**
     * 最大重试次数.
     */
    private static final int MAX_RETRY_TIMES = 3;

    /**
     * 存储配置.
     */
    protected HsqConfigStorage hsqConfigStorage;

    /**
     * 公共服务.
     */
    private HsqCommonService hsqCommonService = new HsqCommonService(this);

    /**
     * 支付服务.
     */
    private HsqPayService hsqPayService = new HsqPayService(this);

    /**
     * 商户服务.
     */
    private HsqMerchantService hsqMerchantService = new HsqMerchantService(this);

    public BaseHsqService(final HsqConfigStorage tiktokConfigStorage) {
        this.hsqConfigStorage = tiktokConfigStorage;
    }

    /**
     * 公共相关接口服务.
     *
     * @return 公共相关接口服务
     */
    @Override
    public HsqCommonService getHsqCommonService() {
        return hsqCommonService;
    }

    /**
     * 支付相关接口服务.
     *
     * @return 支付相关接口服务
     */
    @Override
    public HsqPayService getHsqPayService() {
        return hsqPayService;
    }

    /**
     * 商户相关接口服务.
     *
     * @return 商户相关接口服务
     */
    @Override
    public HsqMerchantService getHsqMerchantService() {
        return hsqMerchantService;
    }

    /**
     * 加密业务请求参数数据.
     *
     * @param content 业务请求参数数据
     * @return 加密后数据
     */
    @Override
    public String encrypt(final String content) {
        // 1.BASE64加密
        String encode = Base64UC.encode(content);
        // 2.私钥加密
        return RsaUtil.encryptByPrivateKey(encode, getHsqConfigStorage().getPrivateKey());
    }

    /**
     * 解密应答报文体数据.
     *
     * @param result 应答报文体数据
     * @return 解密后数据
     */
    @Override
    public String decrypt(final String result) {
        // 1.公钥解密
        String decrypt = RsaUtil.decryptByPublicKey(result, getHsqConfigStorage().getPublicKey());
        if (StringUC.isBlank(decrypt)) {
            throw new HuiShouQianRuntimeException("公钥解密失败！");
        }
        // 2.BASE64解密
        return Base64UC.decode(decrypt);
    }

    /**
     * 发送POST请求，得到响应字符串.
     *
     * @param url    请求地址
     * @param params 请求参数
     * @return 请求结果
     */
    @Override
    public String post(final String url, final Map<String, Object> params) {
        ValidateUC.strNotEmpty(url, HuiShouQianCheckException.class, "请求地址不能为空！");
        ValidateUC.mapNotEmpty(params, HuiShouQianCheckException.class, "请求参数不能为空！");
        // 加密类型
        if (!params.containsKey(HsqConsts.SIGN_TYPE)) {
            params.put(HsqConsts.SIGN_TYPE, HsqConsts.SIGN_TYPE_CFCA);
        }
        // 请求格式
        if (!params.containsKey(HsqConsts.FORMAT)) {
            params.put(HsqConsts.FORMAT, HsqConsts.FORMAT_JSON);
        }
        log.info("【请求地址】：{}", url);
        log.info("【请求参数】：{}", params);
        String response = HttpUtil.post(url, params, 5000);
        log.info("【响应数据】：{} ", response);
        return response;
    }

    /**
     * 发送POST请求，得到响应对象.
     *
     * @param url    请求地址
     * @param params 请求参数
     * @return 请求结果
     * @throws HuiShouQianException 接口异常
     */
    @Override
    public BaseHsqResponse postObject(final String url, final Map<String, Object> params) throws HuiShouQianException {
        // 发起请求
        String body = this.post(url, params);
        // 数据转换
        BaseHsqResponse response = JSONUtil.toBean(body, BaseHsqResponse.class);
        // 是否响应成功
        if (Boolean.FALSE.equals(response.getSuccess())) {
            throw new HuiShouQianException(response.getErrorCode(), response.getErrorMsg());
        }
        // 解密响应数据
        response.setDecryptData(this.decrypt(response.getResult()));
        return response;
    }

}
